package main

import "fmt"

//这种因式分解关键字的写法一般用于声明全局变量
var (
	globalVar  = 1000
	globalName = "globalVar"
)

const (
	Unknown = 0
	Female  = 1
	Male    = 2
)

type Books struct {
	title   string
	author  string
	subject string
	book_id int
}

type Phone interface {
	call()
}

type Android struct {
}

func (android Android) call() {
	fmt.Println("I am Android , I can call u!")
}

type IPhone struct {
}

func (iphone IPhone) call() {
	fmt.Println("I am IPhone , I can call u!")
}

func main() {
	fmt.Println("Hello Go World!")

	var content = "Content"

	fmt.Println(content)
	fmt.Println(&content) //打印变量内存地址/指针

	var a, b, c = "321", 2, false //多变量命名、赋值、自动推断类型
	fmt.Println(a, b, c)

	fmt.Println(globalVar, globalName)

	const localTag = "TAG" //常量命名
	fmt.Println(localTag)

	fmt.Println("常量枚举：", Unknown, Female, Male)

	shortName := "Short cut to assign a var" //简洁命名变量形式:=
	fmt.Println(shortName)

	var pointerVar int = 20 /*声明实际变量*/
	var ip *int             /*声明指针变量*/

	ip = &pointerVar /*指针变量的存储地址*/

	fmt.Printf("pointerVar 变量的地址是：%x\n", &pointerVar)

	fmt.Printf("ip 变量储存的指针地址：%x\n", ip)
	/*使用指针访问值*/
	fmt.Printf("*ip 变量的值：%d\n", *ip)

	//结构体Start-----------------
	/*创建一个新的结构体*/
	fmt.Println(Books{"Go语言", "John Smith", "Go 教程", 2020202})
	fmt.Println(Books{title: "Go语言", author: "John Smith", subject: "Go 教程", book_id: 2020202})
	fmt.Println(Books{title: "Go语言", author: "John Smith"})

	var Book1 Books
	Book1.title = "Java"
	//结构体End-------------------

	slice := [] int{1, 2, 3} /*create a slice*/
	fmt.Println(slice)

	/*make([]T, length, capacity)*/
	var numbers = make([]int, 3, 5) /*也可以指定容量，其中capacity为可选参数。*/
	printSlice(numbers)

	//切片操作打印Start-------------
	sliceNumbers := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}
	printSlice(sliceNumbers)
	/*打印原始切片*/
	fmt.Println("numbers ==", sliceNumbers)
	/*打印子切片从索引1（包含）到索引4（不包含）*/
	fmt.Println("numbers[1:4] ==", sliceNumbers[1:4])
	/*默认下限为 0*/
	fmt.Println("numbers[:3] ==", sliceNumbers[:3])
	/*默认上限为 len（s）*/
	fmt.Println("numbers[4:] ==", sliceNumbers[4:])

	numbers1 := make([]int, 0, 5)
	printSlice(numbers1)

	/*打印子切片从索引 0（包含）到索引 2（不包含）*/
	numbers2 := sliceNumbers[:2]
	printSlice(numbers2)

	/*打印子切片从索引 2（包含）到索引 5（不包含）*/
	numbers3 := sliceNumbers[2:5]
	printSlice(numbers3)

	/*切片相关添加*/
	var sliceA []int
	printSlice(sliceA)

	/*允许追加空切片*/
	sliceA = append(sliceA, 0)
	printSlice(sliceA)

	/*向切片添加一个元素*/
	sliceA = append(sliceA, 1)
	printSlice(sliceA)

	/*同时添加多个元素*/
	sliceA = append(sliceA, 2, 3, 4)
	printSlice(sliceA)

	/*创建切片 sliceB 是之前切片容器的两倍*/
	sliceB := make([]int, len(sliceA), (cap(sliceA))*2)
	copy(sliceB, sliceA)
	printSlice(sliceB)

	//切片操作打印End---------------

	//Range部分Start---------------

	/*使用range去球一个slice的和。使用数组时基本相同*/
	nums := []int{2, 3, 4}
	sum := 0
	for _, num := range nums {
		sum += num
	}
	fmt.Println("sum:", sum)
	/*在数组上使用range将传入index和值两个变量。上面的那个例子不需要使用该元素的序号，所以我们使用空白符"_"省略。有时候我们确实需要知道它的索引，如下例*/
	for i, num := range nums {
		if num == 3 {
			fmt.Println("index:", i)
		}
	}
	/*range也可以勇哥在map的键值对上*/
	kvs := map[string]string{"a": "apple", "b": "banana"}
	for k, v := range kvs {
		fmt.Printf("%s -> %s\n", k, v)
	}
	/*range可以用来枚举Unicode字符串。第一个参数是字符的索引，第二个是字符（Unicode的值）本身。*/
	for i, c := range "go" {
		fmt.Println(i, c)
	}

	//Range部分End-----------------

	//Map部分Start-----------------
	var countryCapitalMap map[string]string     /*create a map*/
	countryCapitalMap = make(map[string]string) /* get instance*/

	/* map 插入key - value对，各个国家对应对首都*/
	countryCapitalMap["France"] = "Paris"
	countryCapitalMap["Italy"] = "Rome"
	countryCapitalMap["Japan"] = "Tokyo"
	countryCapitalMap["China"] = "Beijing"
	/*使用键输出地图值*/
	for country := range countryCapitalMap {
		fmt.Println(country, "首都是：", countryCapitalMap[country])
	}
	/*查看元素在集合中是否存在*/
	capital, ok := countryCapitalMap["美国"] /*如果确定是真实的，则存在，反之则不存在*/
	fmt.Println("capital:" + capital)
	fmt.Println(ok)
	if ok {
		fmt.Println("美国的首都是", capital)
	} else {
		fmt.Println("美国的首都不存在")
	}

	capitalMap := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New delhi"}
	fmt.Println("Origin Map:")
	/*Print the map*/
	for country := range capitalMap {
		fmt.Println(country, "'s Capital is ", capitalMap[country])
	}
	/*delete certain element*/
	delete(capitalMap, "France")
	fmt.Println("Deleted 'France' item")
	fmt.Println("Map After deletion:")
	for country := range capitalMap {
		fmt.Println(country, "'s capital is ", capitalMap[country])
	}
	//Map部分End-------------------

	//接口部分Start-------------------

	var phone Phone
	phone = new(Android)
	phone.call()

	phone = new(IPhone)
	phone.call()

	//接口部分End---------------------

	//错误处理部分Start----------------



	//错误处理部分End------------------

}

func printSlice(x []int) {
	fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
}
